#include <stdio.h>
#include <stdlib.h>

#include <arbb_vmapi.h>

#include "test.h"

#define ERRCHECK(code) { \
  arbb_error_t err = (code); \
  if (err != arbb_error_none) { \
    fprintf(stderr, "ARBB ERR: %s(code %d) %s:%d\n", arbb_get_error_message(err_details), arbb_get_error_code(err_details), __FILE__, __LINE__); \
  } \
}

void funtest(arbb_context_t ctx, arbb_function_t fun)
{
    arbb_binding_t null_binding;

    arbb_error_details_t err_details;

    arbb_type_t f32ty;
    arbb_variable_t out;
    arbb_variable_t ins[2];
    arbb_global_variable_t gvar[3];

    float val0 = 1.1;
    float val1 = 2.32;

    arbb_set_binding_null(&null_binding);

    // scalar f32
    uint64_t size = 1;
    uint64_t pitch = 4;

    ERRCHECK(arbb_get_scalar_type(ctx, &f32ty, arbb_f32, &err_details));

    ERRCHECK(arbb_create_constant(ctx, &gvar[0], f32ty, &val0, NULL, &err_details));
    ERRCHECK(arbb_create_constant(ctx, &gvar[1], f32ty, &val1, NULL, &err_details));
    ERRCHECK(arbb_create_global(ctx, &gvar[2], f32ty, "ret", null_binding, NULL, &err_details));

    ERRCHECK(arbb_get_variable_from_global(ctx, &ins[0], gvar[0], &err_details));
    ERRCHECK(arbb_get_variable_from_global(ctx, &ins[1], gvar[1], &err_details));
    ERRCHECK(arbb_get_variable_from_global(ctx, &out, gvar[2], &err_details));

    printf("fun test\n");

    ERRCHECK(arbb_execute(fun, &out, ins, &err_details));

    float result = 0.0f;
    ERRCHECK(arbb_read_scalar(ctx, out, &result, &err_details));

    printf("result = %f, expected = %f\n", result, val0 + val1);
}

